%module SDL
%include "enumtypeunsafe.swg"
%include "typemaps.i"

%{
#include "SDL_main.h"
#include "SDL.h"
#include "SDL_types.h"
#include "SDL_video.h"
#include "SDL_events.h"
#include "SDL_version.h"

#include "SDL_image.h"
#include "SDL_ttf.h"
#include "SDL_audio.h"
#include "SDL_mixer.h"


  static JavaVM* cachedVM;
  static jobject callback;

  JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
    cachedVM = vm;
    fprintf(stderr, "JNI_OnLoad\n");
    //main(0,argv);
    return JNI_VERSION_1_4;
  }
    void invokeStuff(JNIEnv* jnienv) {
        jclass jc = (*jnienv)->GetObjectClass(jnienv,callback);        
        jmethodID mid = (*jnienv)->GetMethodID(jnienv, jc, "callback", "()V");
        if (mid == 0) {
            fprintf(stderr,"mid = 0!\n");
            return;
        }
        (*jnienv)->CallVoidMethod(jnienv, callback, mid, 0); 
        fprintf(stderr,"called a void method\n");
    }
  
    void setCallback(jobject obj) {
        fprintf(stderr,"setting the callback\n");
        JNIEnv * jenv;
        (*cachedVM)->GetEnv(cachedVM, (void**)&jenv, JNI_VERSION_1_4);
        callback = (*jenv)->NewGlobalRef(jenv,obj);
        //invokeStuff(jenv);
    }

    
  int main(int argc, char *argv[]) {
        fprintf(stderr, "c wrapper main is called\n");
        JNIEnv * jenv;
        (*cachedVM)->GetEnv(cachedVM, (void**)&jenv, JNI_VERSION_1_4);
        invokeStuff(jenv);
        return 0;
    }
    
    
    
    void init_mac() {
        fprintf(stderr,"initing SDL for Mac\n");
        JNIEnv * jenv;
        (*cachedVM)->GetEnv(cachedVM, (void**)&jenv, JNI_VERSION_1_4);
        char **argv;
        main2(0,argv);
    }
    void init() {
        fprintf(stderr,"initing SDL\n");
        JNIEnv * jenv;
        (*cachedVM)->GetEnv(cachedVM, (void**)&jenv, JNI_VERSION_1_4);
        invokeStuff(jenv);
    }

    jobject SWIG_getPixelDirectByteBuffer(SDL_Surface *surface) {
    JNIEnv * jenv;
    jobject buffer;

    (*cachedVM)->GetEnv(cachedVM, (void**)&jenv, JNI_VERSION_1_4);

    buffer = (*jenv)->NewDirectByteBuffer(jenv, surface->pixels, surface->w * surface->h * surface->format->BytesPerPixel);
    if (buffer == NULL) {
      jclass clazz = (*jenv)->FindClass(jenv, "java/lang/NullPointerException");
      (*jenv)->ThrowNew(jenv, clazz, "null returned from NewDirectByteBuffer call!");
      return NULL;
    }
    
    return buffer;
  }
  /*
  void setPixel(SDL_Surface *screen, int x, int y, Uint32 color) {
    Uint32 *bufp;

    bufp = (Uint32 *)screen->pixels + y*screen->pitch/4 + x;
    *bufp = color;
  }
  Uint32 getPixel(SDL_Surface *screen, int x, int y) {
    Uint32 *bufp;

    bufp = (Uint32 *)screen->pixels + y*screen->pitch/4 + x;
    return bufp[0];
  }
 /*
  * Return the pixel value at (x, y)
  * NOTE: The surface must be locked before calling this!
  */
 Uint32 getPixel(SDL_Surface *surface, int x, int y)
 {
     int bpp = surface->format->BytesPerPixel;
     /* Here p is the address to the pixel we want to retrieve */
     Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

     switch (bpp) {
     case 1:
         return *p;

     case 2:
         return *(Uint16 *)p;

     case 3:
         if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
             return p[0] << 16 | p[1] << 8 | p[2];
         else
             return p[0] | p[1] << 8 | p[2] << 16;

     case 4:
         return *(Uint32 *)p;

     default:
         return 0;       /* shouldn't happen, but avoids warnings */
     } // switch
 }

/*
 * Set the pixel at (x, y) to the given value
 * NOTE: The surface must be locked before calling this!
 */
void setPixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
    int bpp = surface->format->BytesPerPixel;
    /* Here p is the address to the pixel we want to set */
    Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;

    switch (bpp) {
    case 1:
        *p = pixel;
        break;

    case 2:
        *(Uint16 *)p = pixel;
        break;

    case 3:
        if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
            p[0] = (pixel >> 16) & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = pixel & 0xff;
        }
        else {
            p[0] = pixel & 0xff;
            p[1] = (pixel >> 8) & 0xff;
            p[2] = (pixel >> 16) & 0xff;
        }
        break;

    case 4:
        *(Uint32 *)p = pixel;
        break;

   default:
        break;           /* shouldn't happen, but avoids warnings */
    } // switch
}

void scaleCopy(SDL_Surface *src, SDL_Surface *dst, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh) {
    int x = 0;
    int y = 0;
    for(x=0; x<dw; x++) {
        for(y=0; y<dh; y++) {
            int ix = (int) (((double)x/(double)dw)*sw);
            int iy = (int) (((double)y/(double)dh)*sh);
            long value = getPixel(src, ix+sx, iy+sy);

            int fx = x + dx;
            int fy = y + dy;
            if(fx >= 0 && fy >= 0 && fx < (dst->w) && fy < (dst->h)) {
                setPixel(dst, fx, fy, value);
            }
        }
    }
}


void noEffect(void *udata, Uint8 *stream, int len)
{
    // you could work with stream here...
    fprintf(stderr, "in the callback %d\n",stream[0]);
}

void doFunky() {
    fprintf(stderr, "registering the postmix callback\n");

// register noEffect as a postmix processor
Mix_SetPostMix(noEffect, NULL);
}
%}


int TTF_GlyphMetrics(TTF_Font *font, Uint16 ch,
				     int *OUTPUT, int *OUTPUT,
                    int *OUTPUT, int *OUTPUT, int *OUTPUT);

%import "begin_code.h"
%include "SDL_main.h"
%include "SDL.h"
%include "SDL_types.h"
%include "SDL_video.h"
%include "SDL_rwops.h"
%include "SDL_version.h"
%include "SDL_error.h"
%include "SDL_active.h"
%include "SDL_keyboard.h"
%include "SDL_keysym.h"
%include "SDL_mouse.h"
%include "SDL_joystick.h"
%include "SDL_events.h"
%include "SDL_timer.h"

%include "SDL_image.h"
%include "SDL_ttf.h"


//%include "SDL_audio.h"
%include "SDL_mixer.h"
%include "close_code.h"

typedef unsigned char Uint8;
typedef unsigned int Uint32;
typedef unsigned short Uint16;
typedef signed int Sint32;
typedef signed short Sint16;

extern jobject SWIG_getPixelDirectByteBuffer(SDL_Surface *surface);
extern void setPixel(SDL_Surface *surface, int x, int y, Uint32 color);
extern Uint32 getPixel(SDL_Surface *surface, int x, int y);
extern void scaleCopy(SDL_Surface *src, SDL_Surface *dst, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh);
extern void setCallback(jobject obj);
extern void init();
extern void init_mac();
extern void doFunky();
                                     
